package org.xiyinjihe.platform.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.xiyinjihe.platform.annotation.Check;
import org.xiyinjihe.platform.dto.req.LoginReqDTO;
import org.xiyinjihe.platform.dto.req.SetUserInfoReqDTO;
import org.xiyinjihe.platform.dto.req.VisitReqDTO;
import org.xiyinjihe.platform.dto.resp.*;
import org.xiyinjihe.platform.error.CommonError;
import org.xiyinjihe.platform.exception.CommonException;
import org.xiyinjihe.platform.po.*;
import org.xiyinjihe.platform.service.SutraService;
import org.xiyinjihe.platform.service.UserService;
import org.xiyinjihe.platform.util.AesCbcUtil;
import org.xiyinjihe.platform.util.HttpClientUtil;

import javax.servlet.http.HttpSession;
import java.util.*;

import static org.xiyinjihe.platform.util.HttpClientUtil.HTTP_GET;

@Api(value = "用户API(包括登录)")
@RestController
@RequestMapping("userApi")
public class UserController {

    private static final Logger logger  = Logger.getLogger(UserController.class);

    @Value("${appId}")
    private String appId;

    @Value("${appSecret}")
    private String appSecret;

    @Value("${wxUrl}")
    private String wxUrl;

    @Value("${jwtSecret}")
    private String JWTSecret;

    @Autowired
    private UserService userService;

    @Autowired
    private SutraService sutraService;

    @ApiOperation(value = "用户登录", notes = "用户登录", response = LoginRespDTO.class)
    @PostMapping("login")
    public LoginRespDTO login(@RequestBody LoginReqDTO req, HttpSession session) {
        logger.debug("login...");
        try {
            //获取sessionKey
            Map<String,String> params = new HashMap<>();
            params.put("appid",appId);
            params.put("secret",appSecret);
            params.put("js_code",req.getCode());
            params.put("grant_type","authorization_code");
            String jsonResult = HttpClientUtil.sendHttpUrl(wxUrl, params, HTTP_GET, HttpClientUtil.UTF8, 3000);
            logger.debug(jsonResult);
            JSONObject object = JSON.parseObject(jsonResult);
            String sessionKey = object.getString("session_key");
            String openid = object.getString("openid");

            // 数据签名校验
            String signature = DigestUtils.sha1Hex(req.getRawData() + sessionKey);
            if(!signature.equals(req.getSignature())){
                throw new CommonException(CommonError.SIGNATURE_ERROR);
            }

            //解析微信用户信息
            String decrypt = AesCbcUtil.decrypt(req.getEncryptedData(), sessionKey, req.getIv(), "UTF-8");
            WxUserInfo wxUserInfo =  parseUserInfo(JSON.parseObject(decrypt));
            logger.debug("nickName:" + wxUserInfo.getNickName());

            //todo:获取用户access_token

            //查询用户是否已经存在
            User user = userService.saveUserInfo(wxUserInfo);

            //生成token
            Algorithm algorithm = Algorithm.HMAC256(JWTSecret);
            Map<String, Object> headerClaims = new HashMap<>();
            headerClaims.put("userId",user.getId());
            headerClaims.put("openId",openid);
            headerClaims.put("nickName",wxUserInfo.getNickName());
            headerClaims.put("unionId",wxUserInfo.getUnionId());
            String token = JWT.create()
                    .withIssuer("auth0")
                    .withHeader(headerClaims)
                    .sign(algorithm);
            logger.debug("generate token: " + token );
            session.setAttribute("token",token);
            //保存token
            userService.saveUserToken(user.getId(),token);

            LoginRespDTO resp = new LoginRespDTO();
            resp.setData(token);
            return resp;
        } catch (Exception e) {
            logger.error(e);
            throw new CommonException(CommonError.SYSTEM_ERROR,e);
        }
    }

    private WxUserInfo parseUserInfo(JSONObject jsonObj) {
        WxUserInfo userInfo = new WxUserInfo();
        userInfo.setNickName(jsonObj.getString("nickName"));
        userInfo.setOpenId(jsonObj.getString("openId"));
        userInfo.setGender(jsonObj.getString("gender"));
        userInfo.setLanguage(jsonObj.getString("language"));
        userInfo.setCountry(jsonObj.getString("country"));
        userInfo.setProvince(jsonObj.getString("province"));
        userInfo.setCity(jsonObj.getString("city"));
        userInfo.setAvatarUrl(jsonObj.getString("avatarUrl"));
        userInfo.setUnionId(jsonObj.getString("unionId"));
        return userInfo;
    }

    @ApiOperation(value = "获取来山目的清单", notes = "获取来山目的清单", response = PurposeListRespDTO.class)
    @GetMapping("getPurposeList")
    public PurposeListRespDTO getPurposeList() {
        logger.debug("purposeList...");
        PurposeListRespDTO resp = new PurposeListRespDTO();
        List<String> purposes = new ArrayList<>();
        purposes.add("1-拜见师父");
        purposes.add("2-请示师父开示");
        purposes.add("3-劳作");
        purposes.add("4-自定义");
        resp.setData(purposes);
        return resp;
    }

    @Check(value="role=user")
    @ApiOperation(value = "获取用户信息", notes = "获取用户信息", response = GetUserInfoRespDTO.class)
    @GetMapping("getUserInfo")
    public GetUserInfoRespDTO getUserInfo(HttpSession session) {
        logger.debug("getUserInfo...");
        long userId = (Long)session.getAttribute("userId");
        User user = userService.getUserInfo(userId);
        GetUserInfoRespDTO resp = new GetUserInfoRespDTO();
        resp.setData(user);
        return resp;
    }

    @Check(value="role=user")
    @ApiOperation(value = "设置用户信息", notes = "设置用户信息", response = SetUserInfoRespDTO.class)
    @PostMapping("setUserInfo")
    public SetUserInfoRespDTO setUserInfo(@RequestBody SetUserInfoReqDTO req, HttpSession session) {
        logger.debug("setUserInfo...");
        long userId = (Long)session.getAttribute("userId");
        userService.setUserInfo(userId,req.getName(),req.getBuddhistName(),req.getHasAsk());
        SetUserInfoRespDTO resp = new SetUserInfoRespDTO();
        resp.setData("ok");
        return resp;
    }

    @Check(value="role=user")
    @ApiOperation(value = "来山请求", notes = "来山请求", response = SetUserInfoRespDTO.class)
    @PostMapping("visit")
    public VisitRespDTO visit(@RequestBody VisitReqDTO req, HttpSession session) {
        logger.debug("visit...");
        long userId = (Long)session.getAttribute("userId");
        VisitWithBLOBs v = new VisitWithBLOBs();
        v.setUserId(userId);
        v.setArriveTime(req.getArriveTime());
        v.setLeaveTime(req.getLeaveTime());
        v.setSubmitTime(new Date());
        v.setTodo(req.getTodo());
        v.setVisitMatters(req.getMatter());
        long id = userService.saveVisit(v);
        VisitRespDTO resp = new VisitRespDTO();
        resp.setData("ok");
        return resp;
    }

//    @Check(value="role=user")
    @ApiOperation(value = "获取经书清单", notes = "获取经书清单", response = SutraListRespDTO.class)
    @GetMapping("getSutraList")
    public SutraListRespDTO getSutraList(@RequestParam(value="sutraType",required=false)  String sutraType) {
        logger.debug("getSutraList...");
        SutraListRespDTO resp = new SutraListRespDTO();
        List<Sutra> sutraList = sutraService.getSutraList(sutraType);
        resp.setData(sutraList);
        return resp;
    }

//    @Check(value="role=user")
    @ApiOperation(value = "获取经书详情", notes = "获取经书详情", response = SutraDetailRespDTO.class)
    @GetMapping("getSutraDetail")
    public SutraDetailRespDTO getSutraDetail(@RequestParam(value="sutraId", required = false) Long sutraId, @RequestParam(value="chapter", required = false) String chapter) {
        logger.debug("getSutraDetail...");
        SutraDetailRespDTO resp = new SutraDetailRespDTO();
        Sutra sutra = sutraService.getSutra(sutraId);
        List<SutraDetail> sutraDetails = sutraService.getSutraDetail(sutraId,chapter);
        SutraDetailInfo sutraDetailInfo = new SutraDetailInfo();
        if(sutra != null){
            sutraDetailInfo.setId(sutra.getId());
            sutraDetailInfo.setTranslator(sutra.getTranslator());
            sutraDetailInfo.setName(sutra.getName());
        }
        if(sutraDetails.size() >0){
            for (SutraDetail sutraDetail : sutraDetails) {
                SutraContent content = new SutraContent();
                content.setPart(sutraDetail.getChapter());
                content.setContent(sutraDetail.getContent());
                sutraDetailInfo.getContents().add(content);
            }
        }
        resp.setData(sutraDetailInfo);
        return resp;
    }


}